//
//  rtmp_streaming_buffer.h
//  RtmpSender
//
//  Created by LSQ on 2020/2/12.
//  Copyright © 2020 Agora. All rights reserved.
//

#pragma once

#include <list>
#include <mutex>

#include "facilities/tools/api_logger.h"
#include "facilities/tools/rtc_callback.h"
#include "rtmp_sender.h"

namespace agora {
namespace rtc {

class IRtmpStreamingBufferObserver {
 public:
  virtual ~IRtmpStreamingBufferObserver() = default;

  virtual void OnRtmpStreamingBufferState(RtmpStreamingBufferState state) = 0;
};

class RtmpStreamingBuffer {
 public:
  struct BufferStatistic {
    uint64_t push_video_frame_cnt_;
    uint64_t push_audio_frame_cnt_;
    uint64_t skip_video_pframe_cnt_;
    uint64_t skip_video_iframe_cnt_;
    uint64_t pop_video_frame_cnt_;
    uint64_t pop_audio_frame_cnt_;
  };

 public:
  explicit RtmpStreamingBuffer(utils::worker_type worker, int max_buffer_size = 500);
  ~RtmpStreamingBuffer();
  void CleanUp();
  int PushFrame(const RtmpMediaFrame& frame);
  void PopFirstFrame(RtmpMediaFrame& frame);
  int FrameListSize();
  int RegisterRtmpStreamingBufferObserver(IRtmpStreamingBufferObserver* observer);
  int UnregisterRtmpStreamingBufferObserver(IRtmpStreamingBufferObserver* observer);
  int RemoveTrailingPFrames();
  BufferStatistic GetStatisticInfo();

 private:
  void RemoveAllFrames();
  void RemoveExpireFrame();
  int RemoveExpirePFrames(bool skipIFrame);
  int RemoveExpireIFrames();
  RtmpStreamingBufferState CurrentBufferState();
  void SampleTick();
  bool NeedLogStream() { return commons::need_log(commons::LOG_STREAM); }

 private:
  utils::worker_type rtmp_send_worker_;
  int max_buffer_size_;
  std::mutex list_mutex_;
  std::list<RtmpMediaFrame> frame_list_;
  std::list<RtmpMediaFrame> sort_list_;
  std::list<int> sample_list_;
  std::unique_ptr<commons::timer_base> sample_timer_;
  utils::RtcAsyncCallback<IRtmpStreamingBufferObserver>::Type buffer_observer_;
  int current_interval_ms_;
  BufferStatistic statistics_ = {0};
};

}  // namespace rtc
}  // namespace agora
